#pragma once

#include <iostream>
#include <sstream>
#include <vector>
#include <Eigen/Dense>

enum class LogLevel { INFO, WARNING, ERROR };

class LogStream {
public:
    LogStream(const char* file, int line, LogLevel level) 
        : file_(file), line_(line), level_(level) {}

    // 基础类型输出
    template<typename T>
    LogStream& operator<<(const T& msg) {
        stream_ << msg;
        return *this;
    }

    // vector输出
    template<typename T>
    LogStream& operator<<(const std::vector<T>& vec) {
        stream_ << "\n{";
        for (size_t i = 0; i < vec.size(); ++i) {
            if (i > 0) stream_ << ", ";
            *this << vec[i];  // 递归调用
        }
        stream_ << "}";
        return *this;
    }

    // vector<uint8_t>输出
    LogStream& operator<<(const std::vector<uint8_t>& vec) {
        stream_ << "\n[";
        for (size_t i = 0; i < vec.size(); ++i) {
            if (i > 0) stream_ << ", ";
            *this << static_cast<uint32_t>(vec[i]);  // 递归调用
        }
        stream_ << "]";
        return *this;
    }

    // vector<uint8_t>输出
    template<typename T>
    LogStream& operator<<(const std::vector<std::vector<T>*>& vec) {
        stream_ << "\n[";
        for (size_t i = 0; i < vec.size(); ++i) {
            if (i > 0) stream_ << ", ";
            *this << (*vec[i]);  // 递归调用
        }
        stream_ << "]";
        return *this;
    }

    // Eigen::MatrixXd输出
    LogStream& operator<<(const Eigen::MatrixXd& matrix) {
        stream_ << "\n[\n" << matrix << "]";
        return *this;
    }

    // Eigen::MatrixXf输出
    LogStream& operator<<(const Eigen::MatrixXf& matrix) {
        stream_ << "\n[\n" << matrix << "]";
        return *this;
    }

    // Eigen::MatrixXi输出
    LogStream& operator<<(const Eigen::MatrixXi& matrix) {
        stream_ << "\n[\n" << matrix << "]";
        return *this;
    }

    // Eigen::VectorXd 输出
    LogStream& operator<<(const Eigen::VectorXd& vector) {
        stream_ << "\n[\n" << vector << "]";
        return *this;
    }

    // Eigen::VectorXf 输出
    LogStream& operator<<(const Eigen::VectorXf& vector) {
        stream_ << "\n[\n" << vector << "]";
        return *this;
    }

    // Eigen::VectorXi 输出
    LogStream& operator<<(const Eigen::VectorXi& vector) {
        stream_ << "\n[\n" << vector << "]";
        return *this;
    }

    ~LogStream() {
        const char* levelStr = "";
        switch (level_) {
            case LogLevel::INFO:    levelStr = "INFO"; break;
            case LogLevel::WARNING: levelStr = "WARN"; break;
            case LogLevel::ERROR:   levelStr = "ERROR"; break;
        }
        std::cout << "[" << levelStr << "][" << file_ << ":" << line_ << "] " 
                  << stream_.str() << std::endl;
    }

private:
    std::ostringstream stream_;
    const char* file_;
    int line_;
    LogLevel level_;
};

// 宏定义
#define LogInfo() LogStream(__FILE__, __LINE__, LogLevel::INFO)
#define LogWarning() LogStream(__FILE__, __LINE__, LogLevel::WARNING)
#define LogError() LogStream(__FILE__, __LINE__, LogLevel::ERROR)
